package sel.me.java.learning.common.base.utils.time;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.Days;
import org.joda.time.Hours;
import org.joda.time.Months;
import org.joda.time.Seconds;
import org.joda.time.Years;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import java.util.Date;
import java.util.TimeZone;


public class TimeUtils {

	private static String[] TIMESTAMP_PATTERN = { 
			"yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd", "yyyy-MM-dd HH:mm"
	};

    public static final int TYPE_SECOND = 1;
    public static final int TYPE_HOUR   = 2;
    public static final int TYPE_DAY    = 3;
    public static final int TYPE_MONTH  = 4;
    public static final int TYPE_YEAR   = 5;

    /**
     * @param year
     * @param monthOfYear
     * @param dayOfMonth
     * @param hourOfDay
     * @param minuteOfHour
     * @param secondOfMinute
     * @param millisOfSecond
     *
     * @return
     */
    public static Date createDate(int year, int monthOfYear, int dayOfMonth, int hourOfDay, int minuteOfHour,
                                  int secondOfMinute, int millisOfSecond) {
        DateTime date = new DateTime(year, monthOfYear, dayOfMonth, hourOfDay, minuteOfHour, secondOfMinute,
                                     millisOfSecond);
        return date.toDate();
    }

    /**
     * @param year
     * @param monthOfYear
     * @param dayOfMonth
     *
     * @return
     */
    public static Date createDate(int year, int monthOfYear, int dayOfMonth) {
        return createDate(year, monthOfYear, dayOfMonth, 0, 0, 0, 0);
    }

    /**
     * @param date
     * @param days
     */
    public static Date plusDays(Date date, int days) {
        if (date != null) {
            DateTime dateTime = new DateTime(date);

            DateTime plusDays = dateTime.plusDays(days);
            return plusDays.toDate();
        }
        return null;
    }

    /**
     * 计算两个时间的距离天数
     *
     * @param date1
     * @param date2
     */
    public static int daysBetween(Date date1, Date date2) {
        if (date1 != null && date2 != null) {
            DateTime dt1 = new DateTime(date1);
            DateTime dt2 = new DateTime(date2);
            return Days.daysBetween(dt1, dt2).getDays();
        }
        throw new IllegalArgumentException("Params error.");
    }

    /**
     * 计算两个时间的距离
     *
     * @param date1
     * @param date2
     */
    public static int hoursBetween(Date date1, Date date2) {
        if (date1 != null && date2 != null) {
            DateTime dt1 = new DateTime(date1);
            DateTime dt2 = new DateTime(date2);
            return Hours.hoursBetween(dt1, dt2).getHours();
        }
        throw new IllegalArgumentException("Params error.");
    }

    /**
     * 计算两个时间的距离
     *
     * @param date1
     * @param date2
     */
    public static int yearsBetween(Date date1, Date date2) {
        if (date1 != null && date2 != null) {
            DateTime dt1 = new DateTime(date1);
            DateTime dt2 = new DateTime(date2);
            return Years.yearsBetween(dt1, dt2).getYears();
        }
        throw new IllegalArgumentException("Params error.");
    }

    /**
     * 计算两个时间的距离
     *
     * @param date1
     * @param date2
     */
    public static int secondsBetween(Date date1, Date date2) {
        if (date1 != null && date2 != null) {
            DateTime dt1 = new DateTime(date1);
            DateTime dt2 = new DateTime(date2);
            return Seconds.secondsBetween(dt1, dt2).getSeconds();
        }
        throw new IllegalArgumentException("Params error.");
    }

    /**
     * 计算两个时间的距离
     *
     * @param date1
     * @param date2
     */
    public static int monthsBetween(Date date1, Date date2) {
        if (date1 != null && date2 != null) {
            DateTime dt1 = new DateTime(date1);
            DateTime dt2 = new DateTime(date2);
            return Months.monthsBetween(dt1, dt2).getMonths();
        }
        throw new IllegalArgumentException("Params error.");
    }

    /**
     * @param date1
     * @param date2
     * @param type  1  second 2  hour 3  day 4  month 5  year
     *
     * @return
     */
    public static int between(Date date1, Date date2, int type) {

        switch (type) {
            case TYPE_SECOND:

                return secondsBetween(date1, date2);
            case TYPE_HOUR:

                return hoursBetween(date1, date2);
            case TYPE_DAY:

                return daysBetween(date1, date2);
            case TYPE_MONTH:

                return monthsBetween(date1, date2);
            case TYPE_YEAR:

                return yearsBetween(date1, date2);
        }

        throw new IllegalArgumentException("Params error.");
    }

    /**
     * @param date
     * @param years
     */
    public static Date plusYears(Date date, int years) {
        if (date != null) {
            DateTime dateTime = new DateTime(date);

            DateTime plusDays = dateTime.plusYears(years);
            return plusDays.toDate();
        }
        return null;
    }

    /**
     * @param date
     * @param weeks
     */
    public static Date plusWeeks(Date date, int weeks) {
        if (date != null) {
            DateTime dateTime = new DateTime(date);

            DateTime plusDays = dateTime.plusWeeks(weeks);
            return plusDays.toDate();
        }
        return null;
    }

    /**
     * @param date
     * @param seconds
     */
    public static Date plusSeconds(Date date, int seconds) {
        if (date != null) {
            DateTime dateTime = new DateTime(date);

            DateTime plusDays = dateTime.plusSeconds(seconds);
            return plusDays.toDate();
        }
        return null;
    }

    /**
     * @param date
     * @param months
     */
    public static Date plusMonths(Date date, int months) {
        if (date != null) {
            DateTime dateTime = new DateTime(date);

            DateTime plusDays = dateTime.plusMonths(months);
            return plusDays.toDate();
        }
        return null;
    }

    /**
     * @param date
     * @param minutes
     */
    public static Date plusMinutes(Date date, int minutes) {
        if (date != null) {
            DateTime dateTime = new DateTime(date);

            DateTime plusDays = dateTime.plusMinutes(minutes);
            return plusDays.toDate();
        }
        return null;
    }

    /**
     * @param date
     * @param millis
     */
    public static Date plusMillis(Date date, int millis) {
        if (date != null) {
            DateTime dateTime = new DateTime(date);

            DateTime plusDays = dateTime.plusMillis(millis);
            return plusDays.toDate();
        }
        return null;
    }

    /**
     * 获取当前时间
     *
     * @return
     */
    public static Date currentTime() {
        return DateTime.now().toDate();
    }

    /**
     * @param date
     * @param hours
     */
    public static Date plusHours(Date date, int hours) {
        if (date != null) {
            DateTime dateTime = new DateTime(date);

            DateTime plusDays = dateTime.plusHours(hours);
            return plusDays.toDate();
        }
        return null;
    }

    public static Date parseDate(String strDate) {
        if (StringUtils.isBlank(strDate)) {
            return null;
        }
        for (String pattern : TIMESTAMP_PATTERN) {
            Date parseDateTime = parseDate(strDate, pattern);
            if (parseDateTime != null) {
                return parseDateTime;
            }
        }
        return null;
    }

    /**
     * @param strDate
     *
     * @return
     */
    public static Date parseDate(String strDate, String pattern) {
        if (StringUtils.isBlank(strDate)) {
            return null;
        }

        DateTime parseDateTime = null;
        try {
            DateTimeFormatter forPattern = DateTimeFormat.forPattern(pattern);
            parseDateTime = forPattern.parseDateTime(strDate);
        } catch (Exception e) {
            // ignore the exception
        }
        if (parseDateTime != null) {
            return parseDateTime.toDate();
        }
        return null;
    }

    /**
     * @param date
     *
     * @return
     */
    public static String parseDate(Date date) {
        return parseDate(date, TIMESTAMP_PATTERN[0]);
    }

    /**
     * @param date
     *
     * @return
     */
    public static String parseShortDate(Date date) {
        return parseDate(date, TIMESTAMP_PATTERN[1]);
    }

    public static String parseDate(Date date, String pattern) {
        if (date == null) {
            return "";
        }
        DateTimeFormatter forPattern = DateTimeFormat.forPattern(pattern);
        return forPattern.print(date.getTime());
    }

    public static void main(String[] args) {

        //        Date date = TimeUtils.currentTime();
        //
        //        date.setMonth(0);
        //        date.setDate(30);
        //
        //        final String s = TimeUtils.parseDate(date);
        //
        //        System.out.println(s);
        //
        //        final Date date1 = TimeUtils.plusMonths(date, 1);
        //
        //        final String s1 = TimeUtils.parseDate(date1);
        //
        //        System.out.println(s1);

        //        System.out.println(TimeUtils.parseDate("Wed, 01-Feb-2017 02:41:05 GMT", "EEE, dd-MMM-yyyy HH:mm:ss zzz"));

        final DateTimeZone gmt = DateTimeZone.forTimeZone(TimeZone.getTimeZone("GMT"));

        System.out.println(gmt);

        System.out.println(TimeUtils.parseDate("01-Feb-2017 02:41:05 GMT", "01-MMM-yyyy HH:mm:ss zzz"));

        //        System.out.println(TimeUtils.parseDate("Wed", "EEE"));

    }
}
